package cn.yto.print.listener;

import cn.yto.print.config.ThreadPoolManager;
import cn.yto.print.constants.AssistantConstants;
import cn.yto.print.enums.PluginRegistryEnum;
import cn.yto.print.plugins.PluginInstalledManager;
import cn.yto.print.utils.CommonUtil;
import cn.yto.print.utils.PluginInstalledUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class PluginInstalledMonitor implements AutoCloseable {

    private static final Logger logger = LogManager.getLogger(PluginInstalledMonitor.class);

    private static volatile PluginInstalledMonitor instance;
    private final ScheduledExecutorService scheduler;
    private final Map<String, Set<SoftwareListener>> listeners;
    private final Map<PluginRegistryEnum, Long> processCheckIntervals;

    // 监控是否处于激活状态
    private boolean monitoringActive;

    /**
     * 私有构造方法
     */
    private PluginInstalledMonitor() {
        scheduler = ThreadPoolManager.getSingleScheduledExecutor();
        listeners = new ConcurrentHashMap<>();
        processCheckIntervals = Collections.synchronizedMap(
                new EnumMap<>(PluginRegistryEnum.class)
        );
        monitoringActive = false;
        if (instance != null) {
            throw new IllegalStateException("PluginInstalledMonitor singleton instance already exists");
        }
    }

    public static PluginInstalledMonitor getInstance() {
        if (instance == null) {
            synchronized (PluginInstalledMonitor.class) {
                if (instance == null) {
                    instance = new PluginInstalledMonitor();
                }
            }
        }
        return instance;
    }

    /**
     * 添加安装状态监听器
     */
    public void addInstalledListener(PluginRegistryEnum pluginRegistry, SoftwareListener listener) {
        addListenerInternal(pluginRegistry, listener, 5000, false);
    }

    public void addInstalledListener(PluginRegistryEnum pluginRegistry, SoftwareListener listener, long checkInterval) {
        addListenerInternal(pluginRegistry, listener, checkInterval, true);
    }

    private void addListenerInternal(PluginRegistryEnum pluginRegistry, SoftwareListener listener, long interval, boolean customInterval) {
        String code = pluginRegistry.getCode();
        listeners.computeIfAbsent(code, k -> ConcurrentHashMap.newKeySet()).add(listener);
        if (customInterval) {
            processCheckIntervals.put(pluginRegistry, interval);
        } else {
            processCheckIntervals.putIfAbsent(pluginRegistry, interval);
        }
        // 确保监控启动
        ensureMonitoringStarted();
    }

    private synchronized void ensureMonitoringStarted() {
        if (!monitoringActive) {
            startMonitoring();
        }
    }

    /**
     * 移除状态监听
     */
    public void removeInstalledListener(PluginRegistryEnum pluginRegistry, SoftwareListener listener) {
        String code = pluginRegistry.getCode();
        listeners.computeIfPresent(code, (k, v) -> {
            v.remove(listener);
            return v.isEmpty() ? null : v;
        });
        if (listeners.isEmpty()) {
            close();
        }
    }

    /**
     * 启动监控
     */
    private synchronized void startMonitoring() {
        if (monitoringActive) {
            return;
        }
        monitoringActive = true;
        scheduler.scheduleAtFixedRate(() -> {
            try {
                performCheckCycle();
            } catch (Exception e) {
                logger.error("插件安装状态监控任务发生异常", e);
            }
        }, 0, 1, TimeUnit.SECONDS);
    }

    private void performCheckCycle() {
        processCheckIntervals.forEach((pluginRegistry, interval) -> {
            if (System.currentTimeMillis() % interval < 1000) {
                triggerCheck(pluginRegistry);
            }
        });
    }

    private void triggerCheck(PluginRegistryEnum pluginRegistry) {
        boolean isInstalled = detectPluginInstalled(pluginRegistry);
        Integer cachedStatus = PluginInstalledManager.getInstance().getInstallStatus(pluginRegistry.getCode());
        boolean wasInstalled = (cachedStatus != null && cachedStatus == AssistantConstants.INSTALLED);

        if (AssistantConstants.UNKNOWN == cachedStatus || isInstalled != wasInstalled) {
            notifyListeners(pluginRegistry, isInstalled);
        }
    }

    /**
     * 检测插件是否已安装
     */
    private boolean detectPluginInstalled(PluginRegistryEnum pluginRegistry) {
        return StringUtils.isNotEmpty(PluginInstalledUtil.getPluginInstallPath(pluginRegistry));
    }

    private void notifyListeners(PluginRegistryEnum pluginRegistry, boolean installed) {
        Set<SoftwareListener> softwareListeners = listeners.getOrDefault(pluginRegistry.getCode(), Collections.emptySet());
        for (SoftwareListener listener : softwareListeners) {
            if (installed) {
                listener.installedComplete(pluginRegistry);
            } else {
                listener.uninstallComplete(pluginRegistry);
            }
        }
    }

    @Override
    public synchronized void close() {
        if (!monitoringActive) {
            return;
        }
        monitoringActive = false;
        CommonUtil.gracefulShutdown(scheduler);
    }

}


